package com.xzzz.common.dblog;

import com.xzzz.common.base.util.SystemUtil;
import com.xzzz.common.base.util.spring.SpringUtil;
import com.xzzz.common.dblog.pojo.LogEntity;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;

/**
 * 日志缓冲队列
 */
@Slf4j
public class LogQueue {

    /**
     * 日志缓冲无界队列
     */
    private static final BlockingQueue<LogEntity> queue = new LinkedBlockingQueue<>();

    /**
     * 单线程定时任务保存日志到数据库
     */
    private static final ScheduledExecutorService dbAppendTask = Executors.newScheduledThreadPool(1);

    /**
     * 日志处理类
     */
    private final LogService logService;

    public LogQueue(LogService logService) {
        this.logService = logService;
    }

    /**
     * 保存日志信息到队列
     *
     * @param logEntity 日志数据
     * @return 成功返回 true，如果此队列已满，则返回 false。
     */
    public static boolean offer(LogEntity logEntity) {
        return queue.offer(logEntity);
    }


    @PostConstruct
    public void init() {
        log.warn("启动日志持久化任务");
        dbAppendTask.scheduleWithFixedDelay(() -> {
            List<LogEntity> logs = new ArrayList<>();
            for (int i = 0; i < 50; i++) {
                LogEntity log = queue.poll();
                if (log != null) {
                    if (ignoreSelfMethod(log)) {
                        continue;
                    }
                    fillMachineInfo(log);
                    logs.add(log);
                }
            }
            logService.save(logs);
        }, 15000L, 5000L, TimeUnit.MILLISECONDS);
    }

    private boolean ignoreSelfMethod(LogEntity logEntity) {
        return "com.xzzz.common.dblog.mapper.LogMapper.save".equals(logEntity.getClassName());
    }

    private void fillMachineInfo(LogEntity log) {
        log.setType("DBAppender");
        log.setAppName(SpringUtil.getAppName());
        log.setIp(SystemUtil.getIp());
        log.setHostName(SystemUtil.getHostName());
    }
}
